// ****************************************************************
// Copyright 2012, Stephan Burguchev
// e-mail: me@sburg.net
// ****************************************************************
// *
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Xml;
using System.Xml.Linq;
using Updater.Common;
using Updater.Wpf.Properties;

namespace Updater.Wpf.ViewModels
{
    public class HtmlUpdateDetailsViewModel : INotifyPropertyChanged
    {
        public HtmlUpdateDetailsViewModel(ChangeLogRecord[] changeLog, bool canDownloadAndInstallUpdate)
        {
            this.ChangeLog = changeLog;
            this.CanDownloadAndInstallUpdate = canDownloadAndInstallUpdate;
            this.ChangeLogHtmlText = this.GenerateHtml();
        }

        public event PropertyChangedEventHandler PropertyChanged;
        public bool CanDownloadAndInstallUpdate { get; private set; }
        public ChangeLogRecord[] ChangeLog { get; private set; }

        public string ChangeLogHtmlText { get; private set; }

        [NotifyPropertyChangedInvocator]
        protected virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = this.PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        private string GenerateHtml()
        {
            XDocument xdoc;
            Assembly assembly = Assembly.GetExecutingAssembly();
            using (Stream s = assembly.GetManifestResourceStream("Updater.Wpf.Resources.Templates.changeLog.html"))
            {
                xdoc = XDocument.Load(s);
            }

            XNamespace ns = xdoc.Root.GetDefaultNamespace();
            XElement body = xdoc.Root.Element(ns + "body").DescendantsAndSelf()
                                .First(e => e.Attribute("id") != null && e.Attribute("id").Value == "updates-container");
            List<XElement> template = body.Elements().Select(e => new XElement(e)).ToList();
            body.RemoveNodes();
            foreach (ChangeLogRecord updateInfo in this.ChangeLog.OrderByDescending(u => u.Version))
            {
                string description = updateInfo.Description;
                string title = updateInfo.Title;
                XElement[] record = template.Select(e => new XElement(e)).ToArray();
                List<XNode> nodes = record.SelectMany(e => e.DescendantNodesAndSelf())
                                          .Where(e => e.NodeType == XmlNodeType.Text).ToList();
                foreach (XText node in nodes)
                {
                    string value = node.Value.Replace("{description}", description).Replace("{title}", title);
                    XElement e = XElement.Parse("<element>" + value + "</element>");
                    node.ReplaceWith(e.Nodes());
                }

                body.Add(record.Cast<object>().ToArray());
            }

            return xdoc.ToString(SaveOptions.OmitDuplicateNamespaces);
        }
    }
}
